package com.gxd.business.bind.interceptor;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.gxd.business.bind.IFieldBind;
import com.gxd.business.bind.aop.FieldBind;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * MyBatis 插件：查询结果后字段绑定（如字典翻译）
 * 支持注解 {@link FieldBind}
 */
@Component
@Intercepts({
		@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class FieldBindInterceptor implements Interceptor {

	@Autowired(required = false)
	private IFieldBind fieldBind;

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		Object result = invocation.proceed();

		if (fieldBind == null || result == null) {
			return result;
		}

		if (result instanceof Collection) {
			Collection<?> list = (Collection<?>) result;
			if (!list.isEmpty()) {
				bindFields(list, list.iterator().next().getClass());
			}
		} else {
			bindFields(Collections.singletonList(result), result.getClass());
		}

		return result;
	}

	/**
	 * 绑定字段数据（支持嵌套处理）
	 */
	private void bindFields(Collection<?> objects, Class<?> beanClass) {
		if (objects == null || objects.isEmpty() || beanClass == null || beanClass == Object.class) {
			return;
		}

		//获取所有标注了 @FieldBind 的字段
		List<Field> bindFields = getBindFields(beanClass);
		if (bindFields.isEmpty()) return;

		for (Object obj : objects) {
			MetaObject metaObject = SpringUtil.getBean(SqlSession.class).getConfiguration().newMetaObject(obj);
			//所有字段进行遍历
			for (Field field : bindFields) {
				FieldBind bind = field.getAnnotation(FieldBind.class);
				Object fieldValue = metaObject.getValue(field.getName()); //字段的值

				// 当key前缀不为空 and 当前字段值不为空 and 待绑定字段存在 进行深度层次翻译映射
				// 例如 （拿到 sex 字段对应的 '0'）
				if (StrUtil.isNotBlank(bind.type().getCode()) && fieldValue != null && bind.target().length > 0 ) {
					fieldBind.setMetaObject(bind, fieldValue, metaObject);
				}
				// 或者 当key为空 and 当前字段值不为空 and 待绑定字段存在 嵌套对象处理
				// 例如 User实体中有一个 Dept ，如果想翻译 Dept 中的 字段 则需要给 Dept 加上 @FieldBind(sourceClass = Dept.Class)
				else if (StrUtil.isBlank(bind.key()) && fieldValue != null && bind.target().length == 0) {
					Class<?> nestedClass = bind.sourceClass();
					if (nestedClass == Object.class) {
						nestedClass = fieldValue.getClass();
					}

					if (fieldValue instanceof Collection) {
						bindFields((Collection<?>) fieldValue, nestedClass);
					} else {
						bindFields(Collections.singletonList(fieldValue), nestedClass);
					}
				}
			}
		}
	}

	/**
	 * 获取所有标注了 @FieldBind 的字段
	 */
	private List<Field> getBindFields(Class<?> clazz) {
		return Stream.of(ReflectUtil.getFields(clazz))
				.filter(field -> field.isAnnotationPresent(FieldBind.class))
				.collect(Collectors.toList());
	}
}